#  coding=utf-8
import pygame
import sys
import random
from random import choice

# 全局定义
pygame.mixer.init()
ipod = pygame.image.load('image/ipod.png')
home = pygame.image.load('image/home.png')
home_start = pygame.image.load('image/home_start.png')
home_close = pygame.image.load('image/home_close.png')
background = pygame.image.load('image/background.png')
snake_body = pygame.image.load('image/snake_body.png')
head_up = pygame.image.load('image/head_up.png')
head_down = pygame.image.load('image/head_down.png')
head_left = pygame.image.load('image/head_left.png')
head_right = pygame.image.load('image/head_right.png')
tail_left = pygame.image.load('image/tail_left.png')
star_img = pygame.image.load('image/star.png')
boom_img = pygame.image.load('image/boom.png')
body_1 = pygame.image.load('image/body_1.png')
body_2 = pygame.image.load('image/body_2.png')
body_3 = pygame.image.load('image/body_3.png')
boom_boom = pygame.image.load('image/boom_boom.png')
box_img = pygame.image.load('image/box_img.png')
hei = pygame.image.load('image/color/hei.png')
hong = pygame.image.load('image/color/hong.png')
huang = pygame.image.load('image/color/huang.png')
lan = pygame.image.load('image/color/lan.png')
qing = pygame.image.load('image/color/qing.png')
zi = pygame.image.load('image/color/zi.png')
got_socre = pygame.mixer.Sound("music/got_score.wav")
color = (hei, hong, huang, lan, qing, zi)

SCREEN_X = 600
SCREEN_Y = 600
MAP_X = 1200
MAP_Y = 1200
HIGHEST_SCORE = 0
IS_BOOM = False
IS_STRAT = False


# 蛇类
# 点以25为单位


class Snake():
    # 初始化各种需要的属性 [开始时默认向右/身体块x5]
    def __init__(self):
        self.dirction = pygame.K_RIGHT
        self.body = []
        for x in range(5):
            self.addnode()

    # 无论何时 都在前端增加蛇块
    def addnode(self):
        left, top = (0, 0)
        if self.body:
            left, top = (self.body[0].left, self.body[0].top)
        node = pygame.Rect(left, top, 25, 25)
        if self.dirction == pygame.K_LEFT:
            if left == 0 and top == 325:
                node.left = SCREEN_Y - 25
            else:
                node.left -= 25
        elif self.dirction == pygame.K_RIGHT:
            if left == SCREEN_Y - 25 and top == 325:
                node.left = 0
            else:
                node.left += 25
        elif self.dirction == pygame.K_UP:
            if top == 0 and left == 325:
                node.top = SCREEN_X - 25
            else:
                node.top -= 25
        elif self.dirction == pygame.K_DOWN:
            if top == SCREEN_X - 25 and left == 325:
                node.top = 0
            else:
                node.top += 25
        self.body.insert(0, node)
        return self.dirction

    # 删除最后一个块
    def delnode(self):
        self.body.pop()

    # 死亡判断
    def isdead(self, booms, buling):
        # 炸死
        for boom in booms:
            if boom.rect == self.body[0]:
                if buling > 0:
                    return False
                else:
                    return True
        # 撞墙
        if self.body[0].x not in range(SCREEN_X):
            return True
        if self.body[0].y not in range(SCREEN_Y):
            return True
        # 撞自己
        # if self.body[0] in self.body[1:]:
        #     return True
        return False

    # 移动！
    def move(self, screen):
        key = self.addnode()
        self.delnode()
        return key

    # 改变方向 但是左右、上下不能被逆向改变
    def changedirection(self, curkey):
        LR = [pygame.K_LEFT, pygame.K_RIGHT]
        UD = [pygame.K_UP, pygame.K_DOWN]
        if curkey in LR + UD:
            if (curkey in LR) and (self.dirction in LR):
                return
            if (curkey in UD) and (self.dirction in UD):
                return
            self.dirction = curkey

    def blit(self, screen, key):
        for rect in self.body:
            index = self.body.index(rect)
            rect_x_y = (rect[0], rect[1])
            if index == 0:
                if key == pygame.K_DOWN:
                    screen.blit(head_down, rect_x_y)
                if key == pygame.K_LEFT:
                    screen.blit(head_left, rect_x_y)
                if key == pygame.K_RIGHT:
                    screen.blit(head_right, rect_x_y)
                if key == pygame.K_UP:
                    screen.blit(head_up, rect_x_y)
            elif index == len(self.body) - 1:
                screen.blit(body_1, rect_x_y)
            elif index == len(self.body) - 2:
                screen.blit(body_2, rect_x_y)
            elif index == len(self.body) - 3:
                screen.blit(body_3, rect_x_y)
            else:
                screen.blit(snake_body, rect_x_y)

    def buling_blit(self, screen, key):
        for rect in self.body:
            index = self.body.index(rect)
            rect_x_y = (rect[0], rect[1])
            if index == 0:
                if key == pygame.K_DOWN:
                    screen.blit(head_down, rect_x_y)
                if key == pygame.K_LEFT:
                    screen.blit(head_left, rect_x_y)
                if key == pygame.K_RIGHT:
                    screen.blit(head_right, rect_x_y)
                if key == pygame.K_UP:
                    screen.blit(head_up, rect_x_y)
            else:
                ran = random.randint(0, len(color) - 1)
                screen.blit(color[ran], rect_x_y)


# 食物类
# 方法： 放置/移除
# 点以25为单位
class Food:
    def __init__(self, count):
        self.rect = pygame.Rect(-25, 0, 25, 25)
        self.colorIndex = random.randint(0, len(color) - 1)
        self.setCount = count

    def remove(self, count):
        self.rect.x = -25
        self.setCount = count

    def set(self):
        self.setCount -= 1
        if self.rect.x == -25 and self.setCount == 0:
            allpos = []
            # 不靠墙太近 25 ~ SCREEN_X-25 之间
            for pos in range(25, SCREEN_X - 25, 25):
                allpos.append(pos)
            self.rect.left = random.choice(allpos)
            self.rect.top = random.choice(allpos)
            self.colorIndex = random.randint(0, len(color) - 1)
            print(self.rect)


class Box(Food):
    def __init__(self, count):
        Food.__init__(self, count)


# 星星类
# 方法： 放置/移除
# 点以25为单位
class Star(Food):
    def __init__(self, count):
        Food.__init__(self, count)


# 炸弹类
# 方法： 放置/移除
# 点以25为单位
class Boom(Food):
    def __init__(self, count):
        Food.__init__(self, count)


def show_text(
        screen,
        pos,
        text,
        color,
        font_bold=False,
        font_size=25,
        font_italic=False):
    # 获取系统字体，并设置文字大小
    cur_font = pygame.font.SysFont("serial", font_size)
    # 设置是否加粗属性
    cur_font.set_bold(font_bold)
    # 设置是否斜体属性
    cur_font.set_italic(font_italic)
    # 设置文字内容
    text_fmt = cur_font.render(text, 1, color)
    # 绘制文字
    screen.blit(text_fmt, pos)


# 开始界面
def isRun(screen):
    global IS_STRAT
    while not IS_STRAT:
        screen.blit(home, (0, 0))
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            if event.type == pygame.MOUSEMOTION:
                x, y = pygame.mouse.get_pos()
                if x in range(337, 516) and y in range(363, 435):
                    screen.blit(home_close, (0, 0))
                if x in range(83, 262) and y in range(363, 435):
                    screen.blit(home_start, (0, 0))
            if event.type == pygame.MOUSEBUTTONDOWN:
                x, y = pygame.mouse.get_pos()
                if x in range(337, 516) and y in range(363, 435):
                    sys.exit()
                if x in range(83, 262) and y in range(363, 435):
                    IS_STRAT = True
            pygame.display.update()


def main():
    global key, HIGHEST_SCORE, buling
    pygame.init()
    screen_size = (SCREEN_X, SCREEN_Y)
    screen = pygame.display.set_mode(screen_size)
    pygame.display.set_caption('Snake')
    # back_music.play()
    clock = pygame.time.Clock()
    scores = 0
    isdead = False
    count = 5
    buling = 0
    slow = 8
    fast = 16
    clockNum = slow
    # 开始界面选择
    if not IS_STRAT:
        isRun(screen)
    # 渲染背景
    screen.blit(home, (0, 0))
    foods = []
    booms = []
    # 蛇/食物
    snake = Snake()
    for i in range(3):
        foods.append(Food(1))
    boom_time = 35
    for i in range(3):
        boom_time += 20
        booms.append(Boom(boom_time))
    star = Star(50)
    box = Box(20)
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_SPACE:
                    clockNum = slow
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    clockNum = fast
                snake.changedirection(event.key)
                # 死后按space重新
                if event.key == pygame.K_SPACE and isdead:
                    return main()
        screen.blit(background, (0, 0))
        pygame.draw.rect(screen, (105, 105, 105), (0, 325, 5, 25))
        pygame.draw.rect(screen, (105, 105, 105), (600, 325, -5, 25))
        pygame.draw.rect(screen, (105, 105, 105), (325, 600, 25, -5))
        pygame.draw.rect(screen, (105, 105, 105), (325, 0, 25, 5))
        # 画蛇身 / 每一步+1分
        if not isdead:
            key = snake.move(screen)
        # 显示死亡文字
        isdead = snake.isdead(booms, buling)
        if isdead:
            HIGHEST_SCORE = max(scores, HIGHEST_SCORE)
            show_text(screen, (100, 200), 'GAME OVER!',
                      (227, 29, 18), False, 60)
            show_text(screen, (140, 250),
                      '...SPACE  TRY  AGAIN...', (0, 0, 22), False, 25)
            # 死亡后景象
            for node in snake.body:
                ran = random.randint(0, len(color) - 1)
                screen.blit(color[ran], node)
        elif buling > 0:
            snake.buling_blit(screen, key)
            buling -= 1
            show_text(screen, (300, 150), 'count down ' + str(buling), (255, 140, 0))
        else:
            snake.blit(screen, key)
        # 食物处理 / 吃到+50分
        # 当食物rect与蛇头重合,吃掉 -> Snake增加一个Node
        for food in foods:
            if food.rect == snake.body[0]:
                scores += 50
                got_socre.play()
                food.remove(random.randint(10, 20))
                snake.addnode()
            food.set()
            screen.blit(color[food.colorIndex], (food.rect[0], food.rect[1]))
        for boom in booms:
            if boom.rect == snake.body[0]:
                if buling > 0:
                    boom.remove(random.randint(20, 30))
                    snake.addnode()
                    scores += 500
                    got_socre.play()
                else:
                    screen.blit(boom_boom, (boom.rect[0] - 30, boom.rect[1] - 30))
            boom.set()
            if not isdead:
                screen.blit(boom_img, (boom.rect[0], boom.rect[1]))
        if star.rect == snake.body[0]:
            # 舍身无敌的步数
            if clockNum == fast:
                buling = 60
            else:
                buling = 30
            star.remove(10)
            got_socre.play()
        if box.rect == snake.body[0]:
            scores += 300
            got_socre.play()
            box.remove(random.randint(35, 45))
            for i in range(3):
                snake.addnode()
        # 食物投递
        star.set()

        box.set()
        screen.blit(star_img, (star.rect[0], star.rect[1]))
        screen.blit(box_img, [box.rect[0], box.rect[1]])
        # 显示分数文字	0,191,255
        show_text(screen, (450, 25), 'Scores: ' + str(scores), (0, 191, 255))
        show_text(screen, (440, 50), 'H_Scores: ' + str(HIGHEST_SCORE), (225, 0, 0))
        if scores > HIGHEST_SCORE and HIGHEST_SCORE != 0 and count > 0:
            count -= 1
            show_text(screen, (300, 150), 'better a record:.... ' + str(HIGHEST_SCORE), (255, 140, 0))
        pygame.display.update()
        clock.tick(clockNum)

if __name__ == '__main__':
    main()
